<?php
// +----------------------------------------------------------------------
// | TOPThink [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// | ThinkImage.class.php 2013-03-05
// +----------------------------------------------------------------------

/* 驱动相关常量定义 */
define('THINKIMAGE_GD',      1); //常量，标识GD库类型
define('THINKIMAGE_IMAGICK', 2); //常量，标识imagick库类型

/* 缩略图相关常量定义 */
define('THINKIMAGE_THUMB_SCALE',     1); //常量，标识缩略图等比例缩放类型
define('THINKIMAGE_THUMB_FILLED',    2); //常量，标识缩略图缩放后填充类型
define('THINKIMAGE_THUMB_CENTER',    3); //常量，标识缩略图居中裁剪类型
define('THINKIMAGE_THUMB_NORTHWEST', 4); //常量，标识缩略图左上角裁剪类型
define('THINKIMAGE_THUMB_SOUTHEAST', 5); //常量，标识缩略图右下角裁剪类型
define('THINKIMAGE_THUMB_FIXED',     6); //常量，标识缩略图固定尺寸缩放类型
define('THINKIMAGE_THUMB_WIDTH',     7); //常量，宽度缩小，高度自适应

/* 水印相关常量定义 */
define('THINKIMAGE_WATER_NORTHWEST', 1); //常量，标识左上角水印
define('THINKIMAGE_WATER_NORTH',     2); //常量，标识上居中水印
define('THINKIMAGE_WATER_NORTHEAST', 3); //常量，标识右上角水印
define('THINKIMAGE_WATER_WEST',      4); //常量，标识左居中水印
define('THINKIMAGE_WATER_CENTER',    5); //常量，标识居中水印
define('THINKIMAGE_WATER_EAST',      6); //常量，标识右居中水印
define('THINKIMAGE_WATER_SOUTHWEST', 7); //常量，标识左下角水印
define('THINKIMAGE_WATER_SOUTH',     8); //常量，标识下居中水印
define('THINKIMAGE_WATER_SOUTHEAST', 9); //常量，标识右下角水印

/**
 * 图片处理驱动类，可配置图片处理库
 * 目前支持GD库和imagick
 * @author 麦当苗儿 <zuojiazi.cn@gmail.com>
 */
class ThinkImage{
    /**
     * 图片资源
     * @var resource
     */
    private $img;

    /**
     * 构造方法，用于实例化一个图片处理对象
     * @param string $type 要使用的类库，默认使用GD库
     */
    public function __construct($type = THINKIMAGE_GD, $imgname = null){
        /* 判断调用库的类型 */
        switch ($type) {
            case THINKIMAGE_GD:
                $class = 'ImageGd';
                break;
            case THINKIMAGE_IMAGICK:
                $class = 'ImageImagick';
                break;
            default:
                throw new Exception('不支持的图片处理库类型');
        }

        /* 引入处理库，实例化图片处理对象 */
        require_once "ImageDriver/{$class}.class.php";
        $this->img = new $class($imgname);
    }

    /**
     * 返回图像宽度
     * @return integer 图像宽度
     */
    public function width(){
        return $this->img->width();
    }

    /**
     * 返回图像高度
     * @return integer 图像高度
     */
    public function height(){
        return $this->img->height();
    }

    /**
     * 返回图像类型
     * @return string 图像类型
     */
    public function type(){
        return $this->img->type();
    }

    /**
     * 返回图像MIME类型
     * @return string 图像MIME类型
     */
    public function mime(){
        return $this->img->mime();
    }

    /**
     * 返回图像尺寸数组 0 - 图像宽度，1 - 图像高度
     * @return array 图像尺寸
     */
    public function size(){
        return $this->img->size();
    }


    public function custom_thumb($dst_w,$dst_h,$filename,$thumb_image_name,$filetype)
    {
        set_time_limit(300);		if($filetype=='gif'){set_time_limit(600);}
//        $filetype = pathinfo($filename, PATHINFO_EXTENSION);
//        if($filetype=='png')
//        {
//            $_img = imagecreatefrompng($filename);
//            $filename = rtrim($filename,$filetype).'jpg';
//            $thumb_image_name = rtrim($thumb_image_name,$filetype).'jpg';
//            $filetype = 'jpg';
//            imagejpeg($_img,$filename,100);
//        }
        list($src_w, $src_h) = getimagesize($filename);
        $size = $this->get_custom_size($src_w,$src_h,$dst_w,$dst_h);//400,258,266,266
        if($src_w>$src_h){
            $this->srcW_gt_srcH($size,$filename,$thumb_image_name,$filetype,$src_w,$src_h);
        }elseif($src_w<$src_h){
            $this->srcW_lt_srcH($size,$filename,$thumb_image_name,$filetype,$src_w,$src_h);
        }elseif($src_w==$src_h){
            $this->srcW_et_srcH($size,$filename,$thumb_image_name,$filetype,$src_w,$src_h);
        }

        return $thumb_image_name;
    }

    public function create_pic_file_imagick($dst_w,$dst_h,$filename,$src_w,$src_h,$savefilename,$dst_x=0,$dst_y=0,$src_x=0,$src_y=0,$type='jpeg')
    {
        $imgObj = new \Imagick(realpath($filename));
        if($type=='gif')
        {
			$canvas = new \Imagick();
			$imgObj = $imgObj->coalesceImages();
			foreach($imgObj as $frame)
			{
				$img = new \Imagick();
				$img->readImageBlob($frame);
				$img->cropImage($src_w, $src_h, $src_x, $src_y);
				$img->thumbnailImage( $dst_w, $dst_h, true );				
				$canvas->addImage( $img );
				$canvas->setImageDelay( $img->getImageDelay() );
				$canvas->setImagePage($dst_w, $dst_h, $dst_x, $dst_y);
			}
			$imgObj->destroy();
			$imgObj = $canvas;
        }		
        else
        {
            $this->custom_crop($dst_w,$dst_h,$dst_x,$dst_y,$src_w, $src_h, $src_x, $src_y,$imgObj);
        }
        $imgObj->setImageFormat($type);
        //JPEG图像设置隔行扫描
        if('jpeg' == $type || 'jpg' == $type)
        {
            $imgObj->setImageInterlaceScheme(1);
        }
        $imgObj->stripImage();
		if($type=='gif')  
        {  
           return  $imgObj->writeImages($savefilename, true);  
        }  
        else  
        {  
           return  $imgObj->writeImage($savefilename);  
        }  
    }

    private function custom_crop($dst_w,$dst_h,$dst_x,$dst_y,$src_w, $src_h, $src_x, $src_y,&$imgObj)
    {
        //裁剪
        if($dst_x != 0 || $dst_y != 0 || $dst_w != $src_w || $dst_h != $src_h)
        {
            $imgObj->cropImage($src_w, $src_h, $src_x, $src_y);
            //调整画布和图片一致
            $imgObj->setImagePage($src_w, $src_h, $src_x, $src_y);
        }
        //调整大小
        if($dst_w != $src_w || $dst_h != $src_h)
        {
            $imgObj->scaleImage($dst_w, $dst_h);
        }
    }


    public function srcW_et_srcH($size,$filename,$thumb_image_name,$filetype,$src_w,$src_h)
    {
        $this->create_pic_file_imagick($size['final']['w'],$size['final']['h'],$filename,$src_w,$src_h,$thumb_image_name,0,0,0,0,$filetype);
    }



    public function srcW_gt_srcH($size,$filename,$thumb_image_name,$filetype,$src_w,$src_h)
    {
        $avg = intval(($size['w']-$size['final']['w'])/2);
        $ret = $this->create_pic_file_imagick($size['w'],$size['h'],$filename,$src_w,$src_h,$thumb_image_name,0,0,0,0,$filetype);
        if($ret)
        {
            list($src_w,$src_h) = getimagesize($thumb_image_name);
            if($this->create_pic_file_imagick($size['w']-$avg,$size['h'],$thumb_image_name,$src_w,$src_h,$thumb_image_name,0,0,-$avg,0,$filetype) && is_array($size['final']))
            {
                list($src_w,$src_h) = getimagesize($thumb_image_name);
                $this->create_pic_file_imagick($size['w']-$avg*2,$size['final']['h'],$thumb_image_name,$src_w,$src_h,$thumb_image_name,0,0,$avg,0,$filetype);
            }
        }
    }
    public function srcW_lt_srcH($size,$filename,$thumb_image_name,$filetype,$src_w,$src_h)
    {
        $avg = intval(($size['h']-$size['final']['h'])/2);
        $ret = $this->create_pic_file_imagick($size['w'],$size['h'],$filename,$src_w,$src_h,$thumb_image_name,0,0,0,0,$filetype);
        if($ret)
        {
            list($src_w,$src_h) = getimagesize($thumb_image_name);
            if($this->create_pic_file_imagick($size['w'],$size['h']-$avg,$thumb_image_name,$src_w,$src_h,$thumb_image_name,0,0,0,-$avg,$filetype) && is_array($size['final']))
            {
                list($src_w,$src_h) = getimagesize($thumb_image_name);
                $this->create_pic_file_imagick($size['final']['w'],$size['h']-$avg*2,$thumb_image_name,$src_w,$src_h,$thumb_image_name,0,0,0,$avg,$filetype);
            }
        }
    }

    public function get_custom_size($src_w,$src_h,$dst_w,$dst_h)
    {
        ////400,258,266,266
        $size = array();
        if($src_w==$src_h)
        {
            $size['final']['w'] = $dst_w;
            $size['final']['h'] = $dst_h;
            return $size;
        }
        if($src_w>=$dst_w && $src_h>=$dst_h)
        {
            if($src_w>$src_h)
            {
                $scale = $dst_h/$src_h;
                $size['w'] = $src_w * $scale;
                $size['h']  = $dst_h;
            }
            elseif($src_w<$src_h)
            {
                $scale = $dst_w/$src_w;
                $size['h'] = $src_h * $scale;
                $size['w']  = $dst_w;
            }
            $size['final']['w'] = $dst_w;
            $size['final']['h'] = $dst_h;
        }
        else
            if($src_w>$dst_w && $src_h<$dst_h)
            {
                $scale = $dst_h/$src_h;
                $size['w'] = $src_w*$scale;
                $size['h'] = $dst_h;
                $size['final']['w'] = $dst_w;
                $size['final']['h'] = $dst_h;
            }
            else
                if($src_w<$dst_w && $src_h>$dst_h)
                {
                    $scale = $dst_w/$src_w;
                    $size['w'] = $dst_w;
                    $size['h'] = $src_h*$scale;
                    $size['final']['w'] = $dst_w;
                    $size['final']['h'] = $dst_h;
                }
                else
                {
                    if($src_w>$src_h)
                    {
                        $scale = $dst_h/$src_h;
                        $size['w'] = $src_w*$scale;
                        $size['h'] = $src_h*$scale;
                    }
                    else
                        if($src_w<$src_h)
                        {
                            $scale = $dst_w/$src_w;
                            $size['w'] = $src_w*$scale;
                            $size['h'] = $src_h*$scale;
                        }
                        else
                        {
                            $size['w'] = $size['h'];
                        }
                    $size['final']['w'] = $dst_w;
                    $size['final']['h'] = $dst_h;
                }
        return $size;
    }


    /**
     * 魔术方法，用于调用驱动方法
     * @param  string $method 方法名称
     * @param  array  $args   参数列表
     * @return object         当前图片处理对象
     */
    public function __call($method, $args){
        call_user_func_array(array($this->img, $method), $args);
        return $this;
    }
}